package com.nova.bluetooth.xunFeiSDK.optionalFunction;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ScrollView;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.iflytek.aiui.AIUIAgent;
import com.iflytek.aiui.AIUIConstant;
import com.iflytek.aiui.AIUIListener;
import com.nova.bluetooth.R;
import com.nova.bluetooth.xunFeiSDK.engine.AiuiEngine;
import com.nova.bluetooth.xunFeiSDK.engine.EngineConstants;
import com.nova.bluetooth.xunFeiSDK.engine.WakeupEngine;
import com.nova.bluetooth.xunFeiSDK.engine.WakeupListener;
import com.nova.bluetooth.xunFeiSDK.utils.CopyAssetsUtils;
import com.nova.bluetooth.xunFeiSDK.utils.ErrorCode;
import com.nova.bluetooth.xunFeiSDK.utils.StreamingAsrUtil;


import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 1.读取assets音频文件后，先降噪唤醒再识别
 * 2.音频路径：filePath
 * 3.线形4mic窄波束算法，数据格式为4mic+2ref。
 * 4.窄波束只能搭配V308版本唤醒词
 *
 * 使用方式：
 * 1.适配多麦风录音，参考文档：https://www.yuque.com/iflyaiui/zzoolv/zmv0f5
 * 2.修改配置文件:WakeupEngine.java中resources/config/vtn.ini修改为resources/config/vtn-zhaiboshu.ini
 * 3.sdk默认加载libvtn.so,所以重命名libvtn_xxx_zhaiboshu.so为libvtn.so
 */
public class ReadFileTest_Zhaiboshu extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = ReadFileTest_Zhaiboshu.class.getSimpleName();
    public ExecutorService executor;   //单线程执行器，保证一个一个文件识别
    Handler handler = new Handler();
    String filePath = "audio/16k16bit-6ch-4mic-zhaiboshu.pcm"; //测试音频
    Button btnAsrResult; //asr结果
    private static int channelNums = 6; //总通道数量为6，4mic+2ref
    private TextView mResText;
    private ScrollView mScrollView;
    // 多麦克算法库
    private WakeupEngine mWakeupEngine;
    // AIUI
    private AIUIAgent mAIUIAgent;
    private int wakeCount = 0;
    /**
     * CAE 回调消息处理
     */
    private WakeupListener wakeupListener = new WakeupListener() {
        @Override
        public void onWakeup(int angle, int beam, int score, String keyWord) {
            AiuiEngine.MSG_wakeup(EngineConstants.WAKEUPTYPE_VOICE);
            wakeCount++;
            setText("唤醒成功,keyword=" + keyWord + " 唤醒次数：" + wakeCount + " score=" + score + " 唤醒角度" + angle);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_asr);
        initLayout();
        // 资源拷贝
        CopyAssetsUtils.portingFile(this);
    }

    private void initLayout() {
        findViewById(R.id.init_sdk).setOnClickListener(this);
        findViewById(R.id.btnStartRecord).setOnClickListener(this);
        findViewById(R.id.btnSave).setVisibility(View.INVISIBLE);
        ((TextView) findViewById(R.id.myTitle)).setText("读音频测试：窄波束");
        mScrollView = findViewById(R.id.scrollView);
        mResText = findViewById(R.id.res_text);
        btnAsrResult = findViewById(R.id.btnStopRecord);
        btnAsrResult.setText("");
        Button btnStartRecord = findViewById(R.id.btnStartRecord);
        btnStartRecord.setText("读音频测试：窄波束");
        mResText.append("-------\n");
    }

    @Override
    public void onClick(View view) {
        int id = view.getId();
        if (id == R.id.init_sdk) {
            initSDK();
        } else if (id == R.id.btnStartRecord) {
            writeAudioTest();
        }
    }

    /**
     * AIUI 回调信息处理
     */
    private AIUIListener mAIUIListener = event -> {
        switch (event.eventType) {
            case AIUIConstant.EVENT_RESULT:
                //处理识别结果
                if (event.info.contains("\"sub\":\"iat")) {
                    JSONObject cntJson = JSON.parseObject(new String(event.data.getByteArray("0"), StandardCharsets.UTF_8));
                    JSONObject text = cntJson.getJSONObject("text");
                    //识别结果
                    String asrResult = StreamingAsrUtil.processIATResult(text);
                    btnAsrResult.setText(asrResult);
                    //最后一次asr返回(ls==true)
                    if (text.getBoolean("ls")) {
                        setText(asrResult);        //打印到屏幕
                    }
                }
                break;

            case AIUIConstant.EVENT_ERROR:
                setText("错误码: " + event.arg1);
                setText("错误信息:" + event.info);
                setText("解决方案:" + ErrorCode.getError(event.arg1) + "\n  错误解决详情参考：https://www.yuque.com/iflyaiui/zzoolv/igbuol");
                break;
            case AIUIConstant.EVENT_STATE:    // 状态事件
                EngineConstants.mAIUIState = event.arg1;
                break;

            default:
                break;
        }
    };

    private void initSDK() {
        //状态初始化
        EngineConstants.isRecording = false;
        //TODO 测试时保存音频分析，量产需关闭保存音频
        EngineConstants.saveAudio=true;
        //使用窄波束配置
        WakeupEngine.cfgPath= "resources/config/vtn-zhaiboshu.ini";
        //获取设备sn,用户可自定义sn，比如型号+mac
        //注意事项1: sn每台设备需要唯一！！！！cae的sn和AIUI的sn要一致
        //注意事项2: 获取的值要保持稳定，否则会重复授权，浪费授权量
        EngineConstants.serialNumber = "iflytek-test";
        // 初始化AIUI(识别+语义+合成）
        mAIUIAgent = AiuiEngine.getInstance(mAIUIListener);
        if (mAIUIAgent != null) {
            setText("AIUI初始化成功");
        } else {
            setText("AIUI初始化失败");
        }

        //初始化CAE(降噪+唤醒)
        mWakeupEngine = WakeupEngine.getInstance(wakeupListener);
        if (mWakeupEngine != null) {
            setText("CAE初始化成功");
        } else {
            setText("CAE初始化失败");
        }

        //保存音频
        EngineConstants.saveAudio = true;
    }


    //根据scrollView 和子view去测量滑动的位置
    private void scrollToBottom(final ScrollView scrollView, final View view) {
        handler.post(() -> {
            if (scrollView == null || view == null) {
                return;
            }
            // offset偏移量。是指当textview中内容超出 scrollview的高度，超出部分就是偏移量
            int offset = view.getMeasuredHeight()
                    - scrollView.getMeasuredHeight();
            if (offset < 0) {
                offset = 0;
            }
            //scrollview开始滚动
            scrollView.scrollTo(0, offset);
        });
    }

    private void setText(final String str) {
        if (Looper.getMainLooper() == Looper.myLooper()) {
            mResText.append(str + " \n");
            scrollToBottom(mScrollView, mResText);
        } else {
            runOnUiThread(() -> {
                mResText.append(str + " \n");
                scrollToBottom(mScrollView, mResText);
            });
        }
    }

    /**
     * 读取外部音频写入 CAE SDK
     */
    private void writeAudioTest() {
        if (EngineConstants.isRecording || EngineConstants.isWriting || mWakeupEngine == null) {
            return;
        }
        setText("读取音频中");
        EngineConstants.isWriting = true;
        executor = Executors.newSingleThreadExecutor();
        byte[] audio = new byte[640 * channelNums];//1声道1ms有32bytes数据。一次只送部分数据去识别
        for (int i = 0; i < 1; i++) {
            Thread speedTestThread = new Thread(() -> {
                // 写入音频
                InputStream in;
                try {
                    in = getResources().getAssets().open(filePath);
                    // 流式读取文件写入aiui
                    while (in.read(audio) != -1) {
                        //可选：根据实际情况做数据过滤
//                        byte[] result=AudioFilter.convert(audio,8,"0,1,2,3,4,5");
                        //可选:去掉直流偏置
//                        AudioAmplify.adjustValue(audio, 31600);
                        //可选:放大增益
//                        AudioAmplify.amplify(audio, 2.2f,6,"0,2");
                        //保存音频
//                        FileUtil.writeFile(audio,"/sdcard/raw.pcm");
//                        WakeupEngine.writeAudioToCAE(audio);

                        WakeupEngine.writeAudioToCAE(audio);
                        Thread.sleep(5);
                    }
                    Log.i(TAG, "音频读取完成");
                    setText("音频读取完成");
                    in.close();
                    EngineConstants.isWriting = false;
                } catch (Exception e) {
                    e.printStackTrace();
                    EngineConstants.isWriting = false;
                }
            });
            executor.execute(speedTestThread);//执行测试
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (wakeupListener != null) {
            wakeupListener = null;
        }
        //销毁唤醒引擎
        WakeupEngine.destroy();
        //结束时一定要调用destroy()，否则aiui的navite方法状态异常
        AiuiEngine.destroy();
    }
}